class Fibonacci {
/** Print out the Fibonacci sequence for values < 50 */
public static void main (String[] args) {
int lo = 1;
int hi = 1;
System.out.println(lo);
while (hi < 50) {
System.out.println(hi);
hi = lo + hi; // new hi
lo = hi - lo; /* new lo is (sum-old lo)
i.e., the old hi [loops -wb]*/
}
}
}
This example declares a Fibonacci class that, like HelloWorld, has a main method. The
first two lines of main declare two variables, hi and lo. Every variable must have a type
that precedes its name. hi and lo are of type int, 32-bit signed [+ or - (wb)] integers with
values in the range -2 to the 32nd power, through 2 to the 32nd power -1.
Java has built-in "primitive" data types to support integers, floating-point, Boolean, and character
values. These primitive types hold data that Java understands directly, as opposed to object types
defined by programmers. Java has no "default" types; the type of every variable must be defined
explicitly. The primitive data types of Java are:
boolean Either true or false
char 16-bit Unicode 1.1 character
byte 8-bit integer (signed)
short 16-bit integer (signed)
int 32-bit integer (signed)
long 64-bit integer (signed)
float 32-bit floating point (IEEE 754-1985)
double 64-bit floating point (IEEE 754-1985)
In the Fibonacci program, we declared hi and lo with initial values of 1. The starting values
are set by initialization expressions, using the = operator, when the variables are declared. The
= operator sets the variable named on the left-hand side to the value of the expression on the right-
hand side. In this program, hi is the last term in the series and lo is the previous term.
Variables are undefined prior to initialization. Should you try to use variables before assigning
a value, the Java compiler will refuse to compile your program until you fix the problem.
The while statement in the example provides one way of looping in Java. The expression
inside the while is evaluated -- if true, the body of the loop is executed and the expression
tested again. The while is repeated until the expression becomes false. If it never becomes
false, the program will run forever, unless something intervenes to break out of the loop, like a
break statement, or an exception handling.
The expression that while tests is a Boolean expression that has the value true or false.
The Boolean expression above tests whether the current high value of the sequence is less than
50. If the high value is less than 50, it's value is printed and the next value calculated. If the
high value equals or exceeds 50, control passes to the first line of code following the body of the
while loop. That is the end of the main method in this example, so the program is finished.
Notice that the println method accepts an integer argument in the Fibonacci example
above, whereas it accepted a string argument in the HelloWorld example. The println
method is one of many methods that are overloaded such that they can accept arguments of
different types.
Exercises: []Add a title to the printed list. []Write a program that generates a different sequence,
such as a table of squares (multiplication is done using *, such as i * i).
Comments in Code
The English-like things scattered through the code are comments. Java has three styles of
comments, all illustrated in the example.
Text following // up to the end of the line is ignored by the compiler, as is text between /* and
the next */ .
Comments enable you to write descriptive text beside your code, to annotate it for future pro-
grammers who may read your code in the future. The "future programmer" may well be you
months or years later. You save yourself effort by commenting your own code. Also, you
often find bugs when you write comments: because explaining what the code is supposed to
do forces you to think about it.
The third kind of comment appears at the very top, between /** and */ . A comment starting with
two asterisks is a documentation comment ("doc comment" for short). Documentation comments
are intended to desrcibe declarations that follow them. The comment in the above example is for
the Main method. A tool called javadoc extracts documentation comments and generates
HTML documentation.
Named Constants
Constants are values like 12, 17, 9, and "Strings Like This". Constants are how
you specify values that are not computed and recomputed, but remain, well, constant for the life
of a program.
Programmers prefer named constants for two reasons. One reason is that the name of the
constant is a form of documentation. The name can (and should) describe what the particular
value is used for.
Another reason is that you define a named constant in a single place in a program. When the
constant needs to be changed or corrected, it can be changed in only one place, easing program
maintenance. Named constants in Java are created by declaring a variable as static and
final, and providing its initial value in the declaration:
class CircleStuff {
static final double p = 3.1416;
}
The value of p can be changed in just one place when we discover that five significant digits of
precision are not enough. We declared p as double -- a double-precision 64-bit floating-
point number. Now we could change p to a more precise value, like 3.14159265358979323846.
You can group related constants within a class. For example, a card game might use these
constants:
class Suit {
final static int CLUBS = 1;
final static int DIAMONDS = 2;
final static int HEARTS = 3;
final static int SPADES = 4;
};
With this declaration, Suit in a program would be accessed as Suit.HEARTS,
Suit.SPADES, and so on, thus grouping all the suit names within the single name Suit.
Unicode Characters
We take a minor diversion to note the psymbol as the name of a constant in the previous
example. In most programming languages, identifiers are usually limited to the letters and digits
available in the ASCII character set.
Java moves you toward the modern world of internationalized software: You write Java code in
Unicode -- an international character-set standard. Unicode characters are 16 bits and provide
a character range large enough to write the major languages used in the world, which is why we
can use p for the name of the value in the example above. p is a valid letter from the Greek
section of Unicode, and therefore valid in Java source. Most existing Java code is written
in ASCII, a 7-bit character standard, or ISO-Latin-1, an 8-bit character standard commonly
called "Latin-1." But they are translated into Unicode before processing so the Java char-
acter set is always Unicode.
Exercises: []Change the HelloWorld application to use a named string constant as the string
to print. []Change the Fibonacci application to use a named constant in its loop instead of a
literal constant.
Flow of Control
"Flow of control" is the term for deciding which statements in a program are executed. The
While loop in the Fibonacci program is one way. Other flow-of-control statements include
if/else, for, switch, do/while, and blocks -- multiple statements grouped within
{ and } . We change the Fibonacci sequence program by numbering the elements of the sequence,
and marking even numbers with an asterisk:
class ImprovedFibonacci {
/** Print out the first few Fibonacci
* numbers, marking evens with a '*' */
static final int MAX_INDEX = 10;
public static void main (String[] args) {
int lo = 1;
int hi = 1;
String mark;
System.out.println("1: " + lo);
for (int I = 2; I < MAX_INDEX; I++) {
if (hi % 2 == 0)
mark = " *";
else
mark = "";
System.out.println(i + ": " + hi + mark);
hi = lo + hi; // new hi
/* new lo is (sum-old lo) i.e., the old hi */
lo = hi - lo;
}
}
}
To number the elements of the sequence, we used a for loop instead of a while loop. A
for loop is shorthand for a while loop, but with an initialization and increment phase added.
The for loop above is equivalent to this while loop:
{
int I = 2;
while (I < MAX_INDEX) {
// .. do the printing stuff
I++;
}
}
The ++ operator in the code fragment above may be unfamiliar if you're new to C-derived
programming languages. The plus-plus operator increments by one the value of any variable
it abuts -- the contents of variable i in this case. The ++ operator is a prefix operator when it
comes before its operand, and postfix when it comes after. Similarly, minus-minus decrements
by one the value of any variable it abuts, and can also be prefix or postfix. The ++ and -- opera-
tors come from the C programming language. In the context of the example above, a statement like
i++;
is equivalent to
i = i + 1;
Beyond simple assignment, Java supports other assignment operators that apply an arithmetic
operation to the value on the left-hand side of the operator. For example, another way to
write i++ in the for loop above would be to write
i += 1;
which adds the value on the right-hand side of the += operator (namely 1) to the variable
on the left-hand side (namely i). Many of the binary operators in Java (operators that take
two operands) can be joined with the = in a similar way.
Inside the for loop we use an if/else to see if the current hi value is even. The if
statement tests the expression between the parentheses. If the expression is true, the first
statement or block in the body of the if is executed. If the expression is false, the statement
or block following the else clause is executed. The else part is optional: if the else is
not present, nothing is done when the expression is false. After figuring out which (if any) clause
to execute, control passes to the code following the body of the if statement.
The example tests if hi is even, using the % or remainder [sometimes called modulus-WedB]
operator. It produces the remainder after dividing the value on the left side by the value on the
right. [In our example at hand -WedB]If the left-side value is even, the remainder 0, and the fol-
lowing statement assigns a string containing the even-numbered indicator to marker. The
else clause is executed for odd numbers, setting marker to an empty string. [Hence the
empty "" -WedB]
The println invocation is more complex, using the + operator to concatenate [Stick things
together just as they present themselves per the concatenation coding requirements. -WedB]
strings representing i, a separator, a string representing hi, and the marker string. The +
operator is a concatenation operator when used with strings, whereas it is an addition operator
when used in arithmetic expressions.
Exercise: []Change the loop so that i counts backward instead of forward.
Classes and Objects
Java, like any object-oriented programming language, provides a tool to solve programming
problems using the notions of classes and objects. Objects in Java have a type; that type is
the object's class. Each class type has two kinds of members, namely fields and methods.
* Fields are data variables associated with a class and its objects. Fields
store results of computations performed by the class's methods.
* Methods contain the executable code of a class. Methods are built from
statements. The way in which methods are invoked and the statements
contained within those methods are what ultimately directs program execution.
Here is the declaration of a simple class that might represent a point on a two-dimensional plane:
class Point {
public double x, y;
}
This Point class has two fields representing the x and y coordinates of a point, and
has (as yet) no methods. A class declaration like this one is, conceptually, a plan that
defines what objects manufactured from that class look like, plus sets of instructions
that define the behavior of those objects. The blueprint of an object adds its maximum
value when you use the plans and instructions in the blueprint to manufacture goods
(objects) from those plans.
Members of a class can have various levels of visibility. The public declaration of x
and y in the Point class means that any code with access to a Point object can read
or modify those values. Other levels of visibility limit member access to code in the
class itself, or to other related classes.
Creating Ojects
Objects are created using an expression containing the new keyword. Creating an object
from a class definition is also known as instantiation; thus objects are often called
instances.
In Java, newly created objects are allocated within an area of syste memory known as the
heap. All objects in Java are created vis object references -- any variable that appears
to hold an object actually contains a reference to that object. Object referenes are null
when they do not reference any object.
Most of the time you can be imprecise in the distinction between actual objects and refer-
ences to objects. You can say "pass the object to the method" when you really mean "pass
an object reference to the method." We are careful about this distinction only where it
makes a difference. Most of the time, you can use "object" and "object reference" inter-
changeably.
Getting back to the Point class defined previously, suppose you are building a graphics
application in which you need to track lots of points. You represent each point by its own
concrete Point object. Here is how you might create and initialize Point objects.
Point lowerLeft = new Point ();
Point upperRight = new Point ();
Point middlePoint = new Point ();
lowerLeft.x = 0.0;
upperLeft.y = 0.0;
upperRight.x = 1280.0;
upperRight.y = 1024.0;
middlePoint.x = 640.0;
middlePoint.y = 512.0;
Each Point object is unique and has its own copy of the x and y fields. Changing
x in the lowerLeft, for example, does not affect the value of x in upperRight object.
The fields in objects are known as instance variables, because there is a unique copy of the
in each object (instance) of the class.
Static or Class Fields
Per-object fields are usually what you need. You usually want a field in one object to be
distinct from the similarly named field in every other object instantiated from that class.
Sometimes, though, you want fields that are shared among all objects of that class. These
shared variables are known as class variables -- variables specific to the class as opposed
[being specific -WedB] to objects of the class.
Why would you want to use class variables? Consider the Sony Walkman factory. Each
Walkman has a unique serial number. In object terms, each Walkman object has its own
unique serial number field. However, the factory needs to keep a record of the next serial
number to be assigned. You don't want to keep that number with every Walkman object --
you'd keep only one copy of that number in the factory, or in object terms, as a class
variable.
In Java, you obtain class-specific fields by declaring them static, and they are therefore
sometimes called static fields. For example, a Point object to represent the origin might
be common enough that you should provide it as a static field in the Point class:
public static Point origin = new Point ();
If this declaration appears inside the declaration of the Pointclass, there will be exactly
one piece of data called Point.origin that always refers to an object at (0,0). This
static field is there no matter how many Point objects are created, even if none
is created. The values of x and y are zero because that is the default for numeric fields
that are not explicitly initialized to a different value.
You saw one static object in your first program. The System class is a standard Java
class that has a static field named out for printing output to the standard output stream.
When you see "field" in this in this chapter, it generally means a per-object field, although
the term "non-static field" is sometimes used for clarity.
The Garbage Collector
After creating an object using new, how do you get rid of the object when you no longer
want it? The answer is simple: You don't. Unused Java objects are automatically reclaimed
by a garbage collector. The garbage collector runs in the background and tracks object
references. When an object no longer has any reference, it can be removed from the storage
allocation heap, although its actual removal may be delayed until a propitious time.
Methods and Parameters
Objects of the Point class as defined above are exposed to manipulation by any code that
has a reference to a Point object, because its fields are declared public. The Point
class is an example of the very simplest kind of class. Indeed, some classes are this simple,
when they are designed to fit purely internal needs for a package, or when simple data
containers are all you need.
The real benefits of object orientation, however, come from hiding the implementation of a
class behind operations performed on its internal data. In Java, operations of a class are
declared via its methods -- instructions that operate on an objects data to obtain results.
Methods access internal implementation details that are otherwise hidden from other objects.
Hiding data behind methods so that it is inaccessible to other objects is the fundamental
basis of data encapsulation.
Methods have zero or more parameters. A method can return a value, or it can be declared
void to indicate that it does not return any value. A method's statements appear in a
block of code between curly braces { and } that follow the method's name and the declar-
ation of its signature. The signature is the name of the method and the number and types
of the method's parameters. If we enhance the Point class with a simple clear method,
it might look like this:
public void clear() {
x=0;
y=0;
}
The clear method has no parameters, hence the empty ( and ) after its name; in addition,
clear is declared void because it does not return any value. Inside a method, fields
and other methods of the class can be named directly -- we can simply say x and y without
an explicit object reference.
Invoking a Method
Objects in general do not operate directly on the data of other objects although, as you saw
in the Point class, a class can make its fields publicly accssible. In general though,
well-designed classes hide their data so that it can be changed only by methods of that class.
To invoke a method, you provide an object reference and the method name, sparated by a dot (.).
Parameters are passed to the method as a comma-separated list of values enclosed in parentheses.
Methods that take no parameters still require the parentheses, with nothing between them. The
object on which the method is invoked (the object receiving the method invocation) is often
known as the receiving object [or] the receiver.
A method may return a single value as a result. To return more than one value from a method,
create an object whose sole purpose is to hold return values in a single unit, and then return
that object.
Here is a method called distance that's part of the Point class shown in previous
examples. The distance method accepts another Point object as a parameter, com-
putes the Euclidean distance between itself and the other point, and returns a double-precision
floating-point result:
public double distance(Point that) {
double xdiff, ydiff;
xdiff = x - that.x;
ydiff = y - that.y;
return Math.sqrt(xdiff ( xdiff + ydiff * ydiff);
}